package com.xdtech.parking.service.impl;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.xdtech.core.dao.BaseDao;
import com.xdtech.core.model.BaseItem;
import com.xdtech.core.orm.Page;
import com.xdtech.core.orm.utils.BeanUtils;
import com.xdtech.parking.dao.ParkingDeviceDao;
import com.xdtech.parking.init.ParkingInit;
import com.xdtech.parking.model.ParkingDevice;
import com.xdtech.parking.protocol.util.ParkRedis;
import com.xdtech.parking.protocol.vo.ParkDeviceInfo;
import com.xdtech.parking.service.ParkingDeviceService;
import com.xdtech.parking.util.ParkingContants;
import com.xdtech.parking.vo.BillDetail;
import com.xdtech.parking.vo.ParkingDeviceItem;
import com.xdtech.web.model.Pagination;

/**
 * 
 * @author max.zheng
 * @create 2015-06-18 14:30:33
 * @since 1.0
 * @see
 */
@Service
public class ParkingDeviceServiceImpl implements ParkingDeviceService {
	private Log log = LogFactory.getLog(ParkingDeviceServiceImpl.class);
	@Autowired
	private ParkingDeviceDao parkingDeviceDao;
	@Autowired
	private BaseDao baseDao;
	/**
	 * @description
	 * @author max.zheng
	 * @create 2015-06-18 14:30:33
	 * @modified by
	 * @param entity
	 */
	public void save(ParkingDevice entity) {
		parkingDeviceDao.save(entity);
		
	}
	/**
	 * @description
	 * @author max.zheng
	 * @create 2015-06-18 14:30:33
	 * @modified by
	 * @param entity
	 */
	public void saveAll(List<ParkingDevice> entities) {
		parkingDeviceDao.saveAll(entities);
	}

	/**
	 * @description
	 * @author max.zheng
	 * @create 2015-06-18 14:30:33
	 * @modified by
	 * @param entity
	 */
	public void delete(ParkingDevice entity) {
		parkingDeviceDao.delete(entity);
	}

	/**
	 * @description
	 * @author max.zheng
	 * @create 2015-06-18 14:30:33
	 * @modified by
	 * @param id
	 */
	public void delete(Long id) {
		parkingDeviceDao.delete(id);
	}

	/**
	 * @description
	 * @author max.zheng
	 * @create 2015-06-18 14:30:33
	 * @modified by
	 * @param id
	 * @return
	 */
	public ParkingDevice get(Long id) {
		return parkingDeviceDao.get(id);
	}

	/**
	 * @description
	 * @author max.zheng
	 * @create 2015-06-18 14:30:33
	 * @modified by
	 * @return
	 */
	public List<ParkingDevice> getAll() {
		return parkingDeviceDao.getAll();
	}

	/**
	 * @description
	 * @author max.zheng
	 * @create 2015-06-18 14:30:33
	 * @modified by
	 * @param pg
	 * @param values
	 * @return
	 */
	public Map<String, Object> loadPageAndCondition(Pagination pg,
			Map<String, String> values) {
		Map<String, Object> results = new HashMap<String, Object>();
		List<Object> parkingDevices = null;
		long rows = 0;
		if (pg!=null) {
			Page<ParkingDevice> page = parkingDeviceDao.findPage(pg,"from ParkingDevice order by createTime desc", values);
			parkingDevices = BeanUtils.copyListProperties(
					ParkingDeviceItem.class, page.getResult());
			rows = page.getTotalItems();
		}else {
			List<ParkingDevice> parkingDeviceList = parkingDeviceDao.find("from ParkingDevice order by id desc", values);
			parkingDevices = BeanUtils.copyListProperties(
					ParkingDeviceItem.class, parkingDeviceList);
			rows = parkingDevices.size();
		}
		results.put("total", rows);
		results.put("rows", parkingDevices);
		return results;
	}

	/**
	 * @description
	 * @author max.zheng
	 * @create 2015-06-18 14:30:33
	 * @modified by
	 * @param item
	 * @return
	 */
	public boolean saveOrUpdateParkingDevice(ParkingDeviceItem item) {
		ParkingDevice parkingDevice = null;
		if (item.getId()==null) {
			parkingDevice = new ParkingDevice();
		}else {
			parkingDevice = parkingDeviceDao.get(item.getId());
		}
		//复制前台修改的属性
		BeanUtils.copyProperties(parkingDevice, item);
		//同步更新到redis
		updateDeviceInfo(parkingDevice);
		return true;
	}

	/**
	 * @description
	 * @author max.zheng
	 * @create 2015-06-18 14:30:33
	 * @modified by
	 * @param parkingDeviceId
	 * @return
	 */
	public ParkingDeviceItem loadParkingDeviceItem(Long parkingDeviceId) {
		ParkingDevice parkingDevice = parkingDeviceDao.get(parkingDeviceId);
		return ParkingDeviceItem.createItem(parkingDevice);
	}

	/**
	 * @description
	 * @author max.zheng
	 * @create 2015-06-18 14:30:33
	 * @modified by
	 * @param id
	 * @return
	 */
	public boolean deleteParkingDeviceInfo(long id) {
		delete(id);
		return true;
	}
	
	/**
	 * @description
	 * @author max.zheng
	 * @create 2015-06-18 14:30:33
	 * @modified by
	 * @param newIds
	 * @return
	 */
	public boolean deleteParkingDeviceInfo(List<Long> parkingDeviceIds) {
		for (Long id : parkingDeviceIds) {
			ParkingDevice parkingDevice = get(id);
			delete(parkingDevice);
			//删除redis里
			ParkRedis.deleteDeviceInfo(parkingDevice.getAreaCode(), parkingDevice.getDeviceCode());
		}
		return true;
	}
	
	public Map<String, Object> loadPageDataByConditions(Pagination pg,
			BaseItem baseItem, String queryName) {
		Map<String, Object> results = new HashMap<String, Object>();
		Page page = baseDao.findPageByNamedQuery(pg, queryName,baseItem);
		results.put("total", page.getTotalItems());
		results.put("rows", page.getResult());
		return results;
	}
	/**
	 * @description
	 * @author max.zheng
	 * @create 2015-06-18 14:30:33
	 * @modified by
	 * @return
	 */
	@Override
	public List<ParkingDeviceItem> loadItems() {
		List<ParkingDevice> parkingDevices = getAll();
		return ParkingDeviceItem.createItems(parkingDevices);
	}
	/**
	 * @description
	 * @author max.zheng
	 * @create 2015-6-20上午10:34:49
	 * @modified by
	 * @param parkDeviceInfos
	 */
	@Override
	public List<ParkDeviceInfo> updateDevicePostInfo(List<ParkDeviceInfo> parkDeviceInfos) {
		List<ParkDeviceInfo> checkRs = new ArrayList<ParkDeviceInfo>();
		for (ParkDeviceInfo parkDeviceInfo : parkDeviceInfos) {
			//校验设备是否存在,主要根据redis里设备
			if (ParkRedis.checkDevIsExit(parkDeviceInfo.getAid(),parkDeviceInfo.getUkid())) {
				//此处后续考虑异步方式
				ParkingDevice parkingDevice = getDeviceByUkey(parkDeviceInfo.getAid(),parkDeviceInfo.getUkid());
				
				//判断有车标记是否变更
				boolean isChangeCar = !(parkDeviceInfo.getSt().getCar()+"").equals(parkingDevice.getHasCar());
				
				//更新
				//设置车位是否有车
				parkingDevice.setHasCar(parkDeviceInfo.getSt().getCar());
				parkingDevice.setGwid(parkDeviceInfo.getGwid());
				// 1-9 表示 电量指数
				parkingDevice.setKwh(parkDeviceInfo.getSt().getKwh());
				//设置车位状态
				parkingDevice.setStatus(parkDeviceInfo.getSt().getOnoff());
				//tag预留设备名称
				parkingDevice.setTag(parkDeviceInfo.getTag());
				updateDeviceInfo(parkingDevice);
				
				
				//统计停车计时相关
				handlerCar(parkingDevice,isChangeCar);
			}else {
				checkRs.add(parkDeviceInfo);
			}
			
		}
		return checkRs;
	}
	
	/**
	 * 
	 * @author max.zheng
	 * @create 2015-6-20下午8:58:48
	 * @modified by
	 * @param parkingDevice
	 */
	private void updateDeviceInfo(ParkingDevice parkingDevice) {
		save(parkingDevice);
		//更新redis里
		ParkRedis.setAreaDeviceInfo(parkingDevice);
//		
	}
	/**
	 * 
	 * @author max.zheng
	 * @create 2015-6-20下午11:27:48
	 * @modified by
	 * @param parkingDevice
	 */
	private void handlerCar(ParkingDevice parkingDevice,boolean isChangeCar) {
		boolean hasCar = parkingDevice.getHasCar()==1;
		if (hasCar&&parkingDevice.getStatus().equals(ParkingContants.PARK_DEVICE_ON_STATUE)&&isChangeCar) {
			//车位无车并且锁是关闭状态=空车位   car=0，onoff=1 开启降
			ParkRedis.freePark(parkingDevice.getAreaCode(),parkingDevice.getDeviceCode(),isChangeCar);
		}else if(!hasCar&&parkingDevice.getStatus().equals(ParkingContants.PARK_DEVICE_OFF_STATUE)&&isChangeCar){
			//状态变更有车 车锁上升（开启）
			//车位有车并且状态是开启，进入停车计时
			ParkRedis.carPark(parkingDevice.getAreaCode(),parkingDevice.getDeviceCode(),isChangeCar);
		}
	}
	/**
	 * 
	 * @author max.zheng
	 * @create 2015-6-20下午8:35:59
	 * @modified by
	 * @param aid
	 * @param ukid
	 * @return
	 */
	private ParkingDevice getDeviceByUkey(String aid, String ukid) {
		ParkingDevice parkingDevice = parkingDeviceDao.findUnique("from ParkingDevice where ukey=?", aid+"_"+ukid);
		return parkingDevice;
	}
	/**
	 * 
	 * @author max.zheng
	 * @create 2015-6-20上午10:37:43
	 * @modified by
	 * @param parkDeviceInfo
	 * @return
	 */
	private ParkingDevice createParkDevice(ParkDeviceInfo parkDeviceInfo) {
		ParkingDevice pd = new ParkingDevice();
		pd.setAreaCode(parkDeviceInfo.getAid());
		pd.setHasCar(parkDeviceInfo.getSt().getCar());
		pd.setDeviceCode(parkDeviceInfo.getUkid());
//		pd.setError(parkDeviceInfo.gete)
		pd.setGwid(parkDeviceInfo.getGwid());
		pd.setKwh(parkDeviceInfo.getSt().getKwh());
//		pd.setSet(parkDeviceInfo.gets)
		pd.setStatus(parkDeviceInfo.getSt().getOnoff());
		pd.setTag(parkDeviceInfo.getTag());
		pd.setUkey(parkDeviceInfo.getAid()+"_"+parkDeviceInfo.getUkid());
		return pd;
	}
	/**
	 * @description
	 * @author max.zheng
	 * @create 2015-6-20下午11:05:35
	 * @modified by
	 * @param areaCode
	 * @param deviceCode
	 * @return
	 */
	@Override
	public boolean checkDeviceCodeIsExit(String areaCode, String deviceCode) {
		ParkingDevice parkingDevice = getDeviceByUkey(areaCode, deviceCode);
		return parkingDevice!=null;
	}
	/**
	 * @description
	 * @author max.zheng
	 * @create 2015-6-21上午1:02:22
	 * @modified by
	 * @param id
	 * @return
	 */
	@Override
	public void turnOn(Long id) {
		ParkingDevice parkingDevice = get(id);
		//升
		parkingDevice.setSetVal("2");
		ParkRedis.setAreaDeviceInfo(parkingDevice);
		//Set值设置
		ParkRedis.setDeviceSetValue(parkingDevice.getUkey(), "2");
		save(parkingDevice);
	}
	/**
	 * @description
	 * @author max.zheng
	 * @create 2015-6-21上午1:02:22
	 * @modified by
	 * @param id
	 * @return
	 */
	@Override
	public void turnOff(Long id) {
		ParkingDevice parkingDevice = get(id);
		//降
		parkingDevice.setSetVal("1");
		ParkRedis.setAreaDeviceInfo(parkingDevice);
		//Set值设置
		ParkRedis.setDeviceSetValue(parkingDevice.getUkey(), "1");
		save(parkingDevice);
	}
	/**
	 * @description
	 * @author max.zheng
	 * @create 2015-7-1下午11:57:00
	 * @modified by
	 * @param deviceUnique
	 */
	@Override
	public void turnOff(String aid,String ukid) {
		ParkingDevice parkingDevice = getDeviceByUkey(aid, ukid);
		//降
		parkingDevice.setSetVal("1");
		ParkRedis.setAreaDeviceInfo(parkingDevice);
		//Set值设置
		ParkRedis.setDeviceSetValue(parkingDevice.getUkey(), "1");
		save(parkingDevice);
	}
	/**
	 * @description
	 * @author max.zheng
	 * @create 2015-7-3下午8:22:22
	 * @modified by
	 * @param aid
	 * @param parkNo
	 * @return
	 */
	@Override
	public BillDetail loadBillInfo(String aid, String parkNo) {
		BillDetail billDetail = new BillDetail();
		if (StringUtils.isNotBlank(aid)&&StringUtils.isNotBlank(parkNo)) {
			ParkingDevice parkingDevice = getDeviceByUkey(aid, parkNo);
			double sum = 0.00;
			DecimalFormat df = new DecimalFormat(".##");
			if (parkingDevice!=null) {
				if (ParkingContants.PARK_BILL_GUDING.equals(parkingDevice.getBilling())) {
					//固定计费
					billDetail.setCostType(1);
					billDetail.setHour(0);
					billDetail.setMinute(0);
					billDetail.setParkNo(parkNo);
					sum = parkingDevice.getCost()*1.0/100;
					
//					String st = df.format(sum);
//					//分转元计算
//					billDetail.setTotal(st);
				}else if (ParkingContants.PARK_BILL_TIME.equals(parkingDevice.getBilling())) {
					//按时计费
					billDetail.setCostType(2);
					long beginTime = ParkRedis.getParkTime(aid, parkNo);
					if (beginTime==0) {
						billDetail.setHour(0);
						billDetail.setMinute(0);
						billDetail.setParkNo(parkNo);
						billDetail.setTotal(0);
					}else {
						//秒
						long takeTime = (System.currentTimeMillis()-beginTime)/1000;
						int hour = (int) (takeTime/3600);
						int minute = (int) ((takeTime%3600)/60);
						
						if (0<minute&&minute<=30) {
							minute = 30;
						}else {
							hour += 1;
							minute = 0;
						}
						
						billDetail.setHour(hour);
						billDetail.setMinute(minute);
						//分转元计算
						sum = parkingDevice.getCost()*(hour+minute*1.0/60)*1.0/100;
						
					}
				}
//				String st = df.format(sum);
				billDetail.setTotal(sum+"");
			}
			
		}
		return billDetail;
	}
	/* (非 Javadoc)
	 * operation
	 * <p>对override方法的补充说明，若不需要则删除此行</p>
	 * 
	 * @param aid
	 * @param parkNo
	 * @param operationType
	 * @return
	 * @see com.xdtech.parking.service.ParkingDeviceService#operation(java.lang.String, java.lang.String, java.lang.String)
	 */
	@Override
	public boolean operation(String aid, String parkNo, String operationType)
	{
		ParkingDevice parkingDevice = getDeviceByUkey(aid, parkNo);
		//降
		parkingDevice.setSetVal(operationType);
		ParkRedis.setAreaDeviceInfo(parkingDevice);
		//Set值设置
		ParkRedis.setDeviceSetValue(parkingDevice.getUkey(), operationType);
		save(parkingDevice);
		return true;
	}
}
